import { Token } from "../ch9";

/**
 * AST抽象类
 */
class HeteroAST {
    token:Token | null;
    constructor(t:Token | null = null){
        this.token = t;
    }
    toString(){
        return this.token?.toString()
    }
    toStringTree(){
        return this.toString();
    }
}

/**
 * 具体实现语法节点
 */
class ExprNode extends HeteroAST{
    constructor(t:Token | null = null){
        super(t)
    }
}

class IntNode extends ExprNode {
    constructor(t:Token){
        super(t)
    }
    toStringTree(){
        return super.toString() + `<type="tINTEGER">` 
    }
}


class AddNode extends ExprNode{
    left:ExprNode;
    right:ExprNode;

    constructor(left:ExprNode,addToken:Token,right:ExprNode){
        super(addToken);
        this.left = left;
        this.right = right;
    }

    toStringTree(){
        let buf = '';
        if(this.left == null || this.right == null){
            return this.toString();
        }
        buf += "("
        buf += this.toString();
        buf += " "
        buf += this.left.toStringTree();
        buf += " "
        buf += this.right.toStringTree()
        buf += ")"
        return buf
    }
}

class VectorNode extends ExprNode {
    elements:ExprNode[] = [];

    constructor(t:Token | null,elements:ExprNode[]){
        super(t);
        this.elements = elements;
    }

    toStringTree(){
        if(this.elements.length == 0){
            return this.toString()
        }

        let buf = '';
        this.elements.forEach((t,i)=>{
            if(i > 0){
                buf += " "
            }
            buf += t.toStringTree()
        })
        return buf;
    }
}

class ListNode extends ExprNode {
    elements:ExprNode[] = [];

    constructor(elements:ExprNode[]){
        super(null);
        this.elements = elements;
    }

    toStringTree(){
        if(this.elements.length == 0){
            return this.toString()
        }
        
        let buf = '';
        this.elements.forEach((t,i)=>{
            if(i > 0){
                buf += " "
            }
            buf += t.toStringTree()
        })
        return buf;
    }
}

export {
    AddNode,
    VectorNode,
    IntNode
}